package com.effectiv.gooruda.rest.api.service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import org.springframework.stereotype.Component;

import com.effectiv.gooruda.rest.api.domain.Session;
import com.effectiv.gooruda.rest.api.domain.User;

import com.effectiv.gooruda.rest.api.operation.SessionOperations;
import com.effectiv.gooruda.rest.api.operation.UserOperations;
import com.effectiv.gooruda.security.rest.RESTSecurityUtil;

@Component
public class SessionServiceImpl implements SessionOperations {

	private final String SESSION_COLLECTION_BASE = "c_session_";

	@Autowired
	private MongoTemplate template;

	@Autowired
	private UserOperations userOperations;

	public Map<String, String> getAttributes(String sessionId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("id").is(sessionId));

		Session s = template.findOne(query, Session.class,
				SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());
		return s.getAttributes();
	}

	public Object getAttribute(String sessionId, String key) {
		return getAttributes(sessionId).get(key);
	}

	public Session findSessionByUser(String userName) {

		Query query = new Query();
		query.addCriteria(Criteria.where("user.UserName").is(userName));

		Session s = template.findOne(query, Session.class,
				SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());

		return s;
	}

	public Session create(String userName) {
		Session s = BeanUtils.instantiate(Session.class);
		s.setAttributes(new HashMap<String, String>());
		s.setUser(userOperations.findByUserName(userName));

		template.save(s, SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());
		return s;
	}

	public Session create(User user) {
		Session s = BeanUtils.instantiate(Session.class);
		s.setAttributes(new HashMap<String, String>());
		s.setUser(user);

		template.save(s, SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());
		return s;
	}

	public void invalidate(String sessionId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("id").is(sessionId));

		Session s = template.findOne(query, Session.class,
				SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());

		s.setInvalidatedOn(new Date());

		template.save(s, SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());

	}

	public Session removeAllAttributes(String sessionId) {
		Query query = new Query();
		query.addCriteria(Criteria.where("id").is(sessionId));

		Session s = template.findOne(query, Session.class,
				SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());
		Map<String, String> attributes = s.getAttributes();
		attributes.clear();

		s.setAttributes(attributes);
		template.save(s, SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());

		return s;
	}

	public Session removeAttribute(String sessionId, String key) {
		Query query = new Query();
		query.addCriteria(Criteria.where("id").is(sessionId));

		Session s = template.findOne(query, Session.class,
				SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());
		Map<String, String> attributes = s.getAttributes();

		attributes.remove(key);

		s.setAttributes(attributes);
		template.save(s, SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());

		return s;
	}

	public Session setAttribute(String sessionId, String key, String value) {
		Query query = new Query();
		query.addCriteria(Criteria.where("id").is(sessionId));

		Session s = template.findOne(query, Session.class,
				SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());
		Map<String, String> attributes = s.getAttributes();

		attributes.put(key, value);

		s.setAttributes(attributes);
		template.save(s, SESSION_COLLECTION_BASE + RESTSecurityUtil.getAppId());

		return s;
	}

}
